package ossutil

import (
	"fmt"
	"github.com/RaymondCode/simple-demo/config"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	uuid "github.com/satori/go.uuid"
	"log"
	"os"
	"strings"
	"time"
)

// Upload 上传文件
// filePath 文件路径
// bucketName 桶名
// @return 文件云端url
func Upload(filePath string, bucketName string) (string, error) {
	log.Println(bucketName)
	client, err := oss.New(
		config.Config.Oss.EndPoint,
		config.Config.Oss.AccessKey,
		config.Config.Oss.SecretKey,
	)
	if err != nil {
		log.Println("OSS连接失败！", err)
		return "", err
	}
	exist, err := client.IsBucketExist(bucketName)
	if !exist {
		log.Println("存储桶不存在！正在创建中！")
		err = client.CreateBucket(bucketName, oss.StorageClass(oss.StorageIA), oss.ACL(oss.ACLPublicRead), oss.RedundancyType(oss.RedundancyZRS))
		if err != nil {
			log.Println("存储桶创建失败!", err)
			return "", err
		}
	}
	var objectName = ParseFileName(filePath)
	err = doUpload(filePath, bucketName, client, objectName)
	if err != nil {
		log.Println("文件上传失败！")
		return "", err
	}
	objectName = strings.Replace(config.Config.Oss.EndPoint,
		"https://oss",
		"https://"+bucketName+".oss", 1) + "/" + objectName
	return objectName, nil
}

// 分段上传文件
// filePath 文件本地路径
// bucketName 桶名
// client oss客户端
// objectName 对象名
func doUpload(filePath string, bucketName string, client *oss.Client, objectName string) error {
	// 获取存储空间
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 将本地文件分片，且分片数量指定为1
	chunks, err := oss.SplitFileByPartNum(filePath, 1)
	fd, err := os.Open(filePath)
	defer fd.Close()
	// 指定过期时间
	expires := time.Date(2100, time.January, 10, 23, 0, 0, 0, time.UTC)
	// 如果需要在初始化分片时设置请求头，请参考以下示例代码
	options := []oss.Option{
		oss.MetadataDirective(oss.MetaReplace),
		oss.Expires(expires),
	}
	// 初始化一个分片上传事件，并指定存储类型为标准存储
	imur, err := bucket.InitiateMultipartUpload(objectName, options...)
	// 上传分片
	var parts []oss.UploadPart
	for _, chunk := range chunks {
		fd.Seek(chunk.Offset, os.SEEK_SET)
		// 调用UploadPart方法上传每个分片。
		part, err := bucket.UploadPart(imur, fd, chunk.Size, chunk.Number)
		if err != nil {
			fmt.Println("Error:", err)
			os.Exit(-1)
		}
		parts = append(parts, part)
	}
	// 指定Object的读写权限为公共读
	objectAcl := oss.ObjectACL(oss.ACLPublicRead)
	// 完成分片上传
	cmur, err := bucket.CompleteMultipartUpload(imur, parts, objectAcl)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	fmt.Println("cmur:", cmur)
	return nil
}

// 获取uuid
func getUUID() string {
	UUID := uuid.NewV4()
	return UUID.String()
}

// ParseFileName 解析文件名，创建一个唯一文件名
// originName 源文件名
func ParseFileName(originName string) string {
	return strings.ReplaceAll(getUUID(), "-", "") + strings.ToLower(originName[strings.LastIndex(originName, "."):])
}

// IsVideo 判断是否是视频
func IsVideo(fileName string) bool {
	var suffix = strings.ToLower(fileName[strings.LastIndex(fileName, "."):])
	var videoSuffix = []string{".avi", ".mp4", ".rmvp"}
	for _, v := range videoSuffix {
		if v == suffix {
			return true
		}
	}
	return false
}
